<template>
  <div
    id="screenfull-container-m3-total"
    ref="screenfull"
    class="container"
    :class="{ 'screenfull-container': isFullscreen }"
  >
    <ButtonGroup
      v-if="buttons.length && !isFullscreen"
      class="button-container"
      :options="buttons"
      @click="handleButtonClick"
    />
    <ScreenfullHead />
    <SearchDetailForm
      ref="form"
      :sale-group-options="saleGroupOptions"
      :has-export="false"
      @search="onSearch"
    />
    <p-table
      row-key="id"
      :custom-header-row="isEdit ? customHeaderRowMinxin : undefined"
      :columns="columns"
      bordered
      :scroll="{ x: '100%', y: isFullscreen ? 'calc(100vh - 300px' : 300 }"
      :pagination="false"
      :data-source="totalData"
      :row-selection="rowSelection"
      @change="handleTableChange"
    />
    <DialogFiledFilter
      :visible.sync="visibleFiled"
      :get-container="getContainer"
      :fileds="fileds"
      :local-key="localKey"
      :default-show="defaultShow"
      :default-fixed="defaultFixed"
      :show.sync="filedShowKeys"
      :fixed.sync="filedFixedKeys"
    />
  </div>
</template>

<script>
import mixinTable from '@/mixins/mixin-table.js';
import { createMonthArray } from '@/utils/time';
import DialogFiledFilter from '@/components/dialog/DialogFiledFilter.vue';
import Decimal from 'decimal.js';
import SearchDetailForm from '@/components/search/SearchDetailForm.vue';
import screenfull from '@/utils/screenfull';
import { postExportDetail, getLastDetailInfo } from '@/api/forecast';
import { downloadFile } from '@/utils/index.js';

import { M_TEMPLATE } from '@/constants/index';

import _ from 'lodash';

const customHeaderCell = (color = '#facd91') => {
  return {
    style: {
      background: color,
    },
  };
};

export default {
  components: {
    DialogFiledFilter,
    SearchDetailForm,
  },
  mixins: [mixinTable],
  props: {
    activeTab: {
      type: String,
      default: '',
    },
    pageType: {
      type: [String, Number],
      default: '',
    },
    localKey: {
      type: String,
      required: true,
    },
    defaultShow: {
      type: Array,
      default: () => [
        'mforecastSalesId',
        'customerName',
        'modelName',
        'category',
      ],
    },
    defaultFixed: {
      type: Array,
      default: () => [
        'mforecastSalesId',
        'customerName',
        'modelName',
        'category',
      ],
    },
    timeRange: {
      type: Array,
      default: () => ['2021-01', '2021-05'],
    },
    hideKeys: {
      type: Array,
      default: () => ['mforecastSalesId'],
    },
    dataSource: {
      type: Array,
      default: () => [],
    },
    mforecastSalesId: {
      type: [Number, String],
      default: undefined,
    },
    planSales: {
      type: Array,
      default: () => [],
    },
    planId: {
      type: Number,
      default: 0,
    },
    isEdit: {
      type: Boolean,
      default: false,
    },

    buttons: {
      type: Array,
      default: () => [
        {
          key: 'export',
          label: '导出',
        },
        {
          key: 'show',
          label: '显示字段',
        },
        {
          key: 'screenfull',
          label: '全屏显示',
        },
      ],
    },
  },
  data() {
    this.M_TEMPLATE = M_TEMPLATE;
    return {
      visibleFiled: false,
      visibleCustomer: false,
      visibleModelNumber: false,
      visibleM9Id: false,
      visibleModelName: false,
      filedsKeys: [],
      currentRowInfo: {},
      checkedGroups: {},
      filedShowKeys: [],
      filedFixedKeys: [],
      dataSourceFilter: [],
      isFullscreen: false,
      lastTimeRange: [],
      condition: {},
    };
  },
  computed: {
    rowSelection() {
      if (this.isEdit) return this.rowSelectionMixin;
      return false;
    },
    totalIndex() {
      return this.totalData.reduce((pre, cur, index) => {
        if (cur.id === 'totalKey') {
          pre.push(index);
        }
        return pre;
      }, []);
    },
    groups() {
      const data = this.dataSourceFilter.reduce((pre, cur) => {
        if (pre[cur.mforecastSalesId]) {
          pre[cur.mforecastSalesId].push(cur);
        } else {
          pre[cur.mforecastSalesId] = [cur];
        }
        return pre;
      }, {});
      Object.keys(data).forEach((group) => {
        data[group].forEach((item, index) => {
          item.index = index;
        });
      });
      return data;
    },
    totalData() {
      if (!this.dataSourceFilter.length) return [];
      const totalKeys = this.totalKeys;

      const data = Object.keys(this.groups).map((group) => {
        const obj = this.groups[group].reduce(
          (pre, cur) => {
            totalKeys.forEach((key) => {
              if (!_.get(pre, key)) {
                _.set(pre, key, 0);
              }
              const tempValue = new Decimal(_.get(pre, key)).plus(
                new Decimal(_.get(cur, key) || 0)
              );
              if (key.startsWith('price')) {
                _.set(pre, key, tempValue.toFixed(2));
              } else {
                _.set(pre, key, tempValue.toFixed());
              }
            });
            return pre;
          },
          { id: 'totalKey', changeRemark: '' }
        );
        return [...this.groups[group], { ...this.groups[group][0], ...obj }];
      });

      const obj = this.dataSourceFilter.reduce(
        (pre, cur) => {
          totalKeys.forEach((key) => {
            if (!_.get(pre, key)) {
              _.set(pre, key, 0);
            }
            const tempValue = new Decimal(_.get(pre, key)).plus(
              new Decimal(_.get(cur, key) || 0)
            );
            if (key.startsWith('price')) {
              _.set(pre, key, tempValue.toFixed(2));
            } else {
              _.set(pre, key, tempValue.toFixed());
            }
          });
          return pre;
        },
        { id: 'totalKey', changeRemark: '' }
      );

      if (Object.keys(this.groups).length > 1) {
        return [...data.flat(1), { ...this.dataSourceFilter[0], ...obj }];
      }
      return data.flat(1);
    },
    saleGroupOptions() {
      return this.planSales.map((item) => {
        return {
          value: item.id,
          label: item.salesGroupName,
        };
      });
    },
    ranges() {
      const months = createMonthArray(this.timeRange);
      return months;
    },
    lastRanges() {
      const ranges = createMonthArray(this.lastTimeRange);
      return ranges.filter((item) => this.ranges.includes(item));
    },
    monthObj() {
      const month = this.ranges.reduce((pre, cur) => {
        if (pre[cur]) {
          pre[cur].push(cur);
        } else {
          pre[cur] = [cur];
        }
        return pre;
      }, {});

      return month;
    },
    lastMonthObj() {
      const month = this.lastRanges.reduce((pre, cur) => {
        if (pre[cur]) {
          pre[cur].push(cur);
        } else {
          pre[cur] = [cur];
        }
        return pre;
      }, {});
      return month;
    },
    totalKeys() {
      const keys = [
        'fcst',
        'lastFcst',
        'price',
        'preAllocated',
        'salesForecast',
        'supplyPlan',
        'salesForecastKsht',
      ];
      const monthkeys = Object.keys(this.monthObj).reduce((pre, cur) => {
        keys.forEach((key) => {
          pre.push(`${key}.${cur}`);
        });
        return pre;
      }, []);
      return [...monthkeys];
    },
    columnLength() {
      const keys = [
        'fcst',
        'lastFcst',
        'price',
        'preAllocated',
        'salesForecast',
        'supplyPlan',
        'salesForecastKsht',
      ];
      const data = this.dataSource[0] || {};
      const length = keys.reduce((pre, key) => {
        const v = data[key] || {};
        pre[key] = Object.keys(v).length;
        return pre;
      }, {});
      return length;
    },
    colIndex() {
      return this.columns.findIndex((item) => item.dataIndex === 'fcst');
    },
    isAllChecked() {
      const checkedLength = Object.keys(this.checkedGroups).filter(
        (el) => this.checkedGroups[el]
      ).length;
      const groupsLenght = Object.keys(this.groups).length;
      return checkedLength === groupsLenght;
    },
    defaultCoulumns() {
      return [
        {
          align: 'center',
          title: '序号',
          dataIndex: 'index',
          width: 80,
          fixed: 'left',
          noOperate: true,
          customRender: (t, r, index) => {
            if (this.totalIndex.includes(index)) {
              return {
                children: (
                  <div style="display: flex;justify-content: flex-start;">
                    {index === this.totalData.length - 1 &&
                    Object.keys(this.groups).length > 1
                      ? '大汇总'
                      : '组内汇总'}
                  </div>
                ),
                attrs: {
                  colSpan: this.colIndex,
                },
              };
            }
            return parseInt(t) + 1;
          },
        },
        {
          align: 'center',
          title: (
            <p-checkbox
              checked={this.isAllChecked}
              vOn:change={this.handleCheckAll}
            />
          ),
          dataIndex: 'selection',
          width: 60,
          fixed: 'left',
          noOperate: true,
          isHide: this.hideKeys.includes('selection'),
          customRender: (value, row, index) => {
            const children = (
              <p-checkbox
                checked={this.checkedGroups[row.mforecastSalesId]}
                vOn:change={(e) => this.handleCheckBox(e, value, row, index)}
              />
            );
            return this.customRender(children, index, row, 'selection');
          },
        },
        {
          align: 'center',
          title: '销售组',
          dataIndex: 'mforecastSalesId',
          required: true,
          width: 120,
          isHide: this.hideKeys.includes('mforecastSalesId'),
          customRender: (value, row, index) => {
            const children = (
              <SelectDefault
                value={value}
                get-popup-container={this.getContainer}
                disabled={!this.isEdit}
                options={this.saleGroupOptions}
                allow-clear={false}
                has-all={false}
                vOn:input={(e) =>
                  this.handleInputChange(
                    e,
                    value,
                    row,
                    index,
                    'mforecastSalesId'
                  )
                }
              />
            );
            return this.customRender(children, index, row, 'mforecastSalesId');
          },
        },
        {
          align: 'center',
          title: '客户简称',
          dataIndex: 'customerName',
          width: 120,
          customRender: (value, row, index) => {
            const children = <TableSpan value={value} />;
            return this.customRender(children, index);
          },
        },

        {
          align: 'center',
          title: 'Model Name',
          dataIndex: 'modelName',
          width: 160,
          customRender: (value, row, index) => {
            const children = (
              <div>
                <InputSearch
                  value={value}
                  isInput={true}
                  isEdit={this.isEdit}
                  vOn:search={() =>
                    this.openDialog('visibleModelName', {
                      value,
                      row,
                      index,
                      dataIndex: 'modelName',
                    })
                  }
                  vOn:change={(e) =>
                    this.handleInputChange(e, value, row, index, 'modelName')
                  }
                />
              </div>
            );
            return this.customRender(children, index);
          },
        },

        {
          align: 'center',
          title: '类别',
          dataIndex: 'category',
          width: 160,
          customRender: (value, row, index) => {
            const children = (
              <SelectDefault
                value={value}
                get-popup-container={this.getContainer}
                disabled={!this.isEdit}
                code="category"
                has-default={false}
                allow-clear={true}
                has-all={false}
                vOn:input={(e) =>
                  this.handleInputChange(e, value, row, index, 'category')
                }
              />
            );
            return this.customRender(children, index);
          },
        },

        {
          align: 'center',
          title: '当前版本FCST（小片Kpcs）',
          dataIndex: 'fcst',
          customHeaderCell: () => customHeaderCell('#d1ebf7'),
          noOperate: true,
          children: this.createMonthColumns({
            key: 'fcst',
            color: '#d1ebf7',
            hasTotal: true,
            months: this.monthObj,
          }),
        },

        {
          align: 'center',
          title: '上一版本FCST（小片Kpcs）',
          dataIndex: 'lastFcst',
          noOperate: true,
          isHide: this.lastRanges.length < 1,
          customHeaderCell: () => customHeaderCell('#facd91'),
          children: this.createMonthColumns({
            key: 'lastFcst',
            color: '#facd91',
            hasTotal: true,
            months: this.lastMonthObj,
          }),
        },
        {
          align: 'center',
          title: '需求变动说明',
          dataIndex: 'changeRemark',
          width: 160,
          noOperate: true,

          customHeaderCell: () => customHeaderCell('#cae5f2'),
          isHide: this.lastRanges.length < 1,
          customRender: (value, row, index) => {
            // const fcst = row.fcst || {};
            // const lastFcst = row.lastFcst || {};
            // const isSame = Object.keys(lastFcst).every((item) => {
            //   const last = JSON.stringify(lastFcst[item]);
            //   const current = JSON.stringify(fcst[item]);
            //   return last === current;
            // });
            // const isDiff = this.isEdit && row.id !== 'totalKey' && !isSame;
            const children = <InputDefault value={value} isEdit={false} />;
            return this.customRender(children, index, row, 'changeRemark');
          },
        },
        {
          align: 'center',
          title: '单价（人民币：元）',
          dataIndex: 'price',
          noOperate: true,
          customHeaderCell: () => customHeaderCell('#b0caec'),
          children: this.createMonthColumns({
            key: 'price',
            color: '#b0caec',
            hasTotal: false,
            months: this.monthObj,
          }),
        },
        {
          align: 'center',
          title: '预分配（小片Kpcs）',
          dataIndex: 'preAllocated',
          noOperate: true,
          // isHide: !this.columnLength['preAllocated'],
          customHeaderCell: () => customHeaderCell('#ddebe2'),
          children: this.createMonthColumns({
            key: 'preAllocated',
            color: '#ddebe2',
            hasTotal: true,
            months: this.monthObj,
          }),
        },
        {
          align: 'center',
          title: '供应计划',
          dataIndex: 'supplyPlan',
          noOperate: true,
          // isHide: !this.columnLength['supplyPlan'],
          customHeaderCell: () => customHeaderCell('#dedbf2'),
          children: this.createMonthColumns({
            key: 'supplyPlan',
            color: '#dedbf2',
            hasTotal: true,
            months: this.monthObj,
          }),
        },
        {
          align: 'center',
          title: '销量预测（小片Kpcs）',
          dataIndex: 'salesForecast',
          noOperate: true,
          // isHide: !this.columnLength['salesForecast'],
          customHeaderCell: () => customHeaderCell('#f3f5e1'),
          children: this.createMonthColumns({
            key: 'salesForecast',
            color: '#f3f5e1',
            hasTotal: true,
            months: this.monthObj,
          }),
        },
        {
          align: 'center',
          title: '销量预测（大板 Ksht）',
          dataIndex: 'salesForecastKsht',
          noOperate: true,
          // isHide: !this.columnLength['salesForecastKsht'],
          customHeaderCell: () => customHeaderCell('#f3f5e1'),
          children: this.createMonthColumns({
            key: 'salesForecastKsht',
            color: '#f3f5e1',
            hasTotal: true,
            months: this.monthObj,
          }),
        },
      ];
    },

    fileds() {
      return this.defaultCoulumns;
    },
    columns() {
      let columns = this.defaultCoulumns.filter((item) => !item.isHide);
      if (this.filedShowKeys.length) {
        columns = columns.filter((item) => {
          return (
            item.required ||
            this.filedShowKeys.includes(item.dataIndex) ||
            item.noOperate
          );
        });
      }
      const left = [],
        right = [];
      columns.forEach((item) => {
        if (
          item.fixed === 'left' ||
          this.filedFixedKeys.includes(item.dataIndex)
        ) {
          left.push({ ...item, fixed: 'left' });
        } else {
          right.push(item);
        }
      });
      return [...left, ...right];
    },
  },
  watch: {
    dataSource: {
      handler(val) {
        this.onSearch();
      },
      immediate: true,
    },
    activeTab: {
      handler(val) {
        this.checkedGroups = [];
        this.$emit('checked', this.checkedGroups, this.groups);
      },
    },
  },
  created() {
    this.rowSelectionMixin.getCheckboxProps = (record) => {
      return {
        props: {
          disabled: record.id === 'totalKey',
        },
      };
    };
    this.handleCheckAll({ target: { checked: true } });
  },
  mounted() {
    this.getLastDetailInfo();
    this.onSearch();
    screenfull.onchange((e) => {
      this.isFullscreen = screenfull.isFullscreen;
    });
  },
  methods: {
    async getLastDetailInfo() {
      const result = await getLastDetailInfo({ id: this.planId });
      const data = result?.data?.data || {};
      this.lastTimeRange = [data.startTime, data.endTime];
      // this.lastTimeRange = ['2021-09-01 00:00:00', '2021-10-01 00:00:00'];
    },

    getContainer() {
      return document.getElementById('screenfull-container-m3-total');
    },
    onSearch(isSearch) {
      if (!this.$refs.form) return;
      if (!isSearch) {
        this.$refs.form.handleReset();
        return;
      }
      const form = (this.$refs.form && this.$refs.form.form) || {};
      const isEmpty = (val) => !val;
      // 销售组
      const isPlanSalesId = (val) =>
        isEmpty(form.planSalesId) || form.planSalesId === val;
      // 应用别
      const isApplication = (val) =>
        isEmpty(form.application) || form.application === val;
      // 形态
      const isAppearance = (val) =>
        isEmpty(form.appearance) || form.appearance === val;
      // 生产地
      const isManufactureArea = (val) =>
        isEmpty(form.manufactureArea) || form.manufactureArea === val;
      // Model Name
      const isModelName = (val) =>
        isEmpty(form.modelName) || val?.includes(form.modelName);
      // 机种
      const isModelNumber = (val) =>
        isEmpty(form.modelNumber) || val?.includes(form.modelNumber);
      // 客户简称 customerCode
      const isCustomerCode = (val) =>
        isEmpty(form.customerCode) || val?.includes(form.customerCode);
      this.dataSourceFilter = this.dataSource.filter((item) => {
        return (
          isPlanSalesId(item.mforecastSalesId) &&
          isApplication(item.application) &&
          isAppearance(item.appearance) &&
          isManufactureArea(item.manufactureArea) &&
          isModelName(item.modelName?.label) &&
          isModelNumber(item.modelNumber?.label) &&
          isCustomerCode(item.customerCode?.label)
        );
      });
      // 重置选择的状态
      this.checkedGroups = [];
      this.$emit('checked', this.checkedGroups, this.groups);
    },
    async screenfullCallback() {
      const ele = this.$refs.screenfull;
      if (screenfull.isEnabled) {
        await screenfull.toggle(ele, { navigationUI: 'hide' });
      }
    },
    handleCheckAll(e) {
      const checked = e.target.checked;
      Object.keys(this.groups).forEach((group) => {
        this.$set(this.checkedGroups, group, checked);
      });
      this.$emit('checked', this.checkedGroups, this.groups);
    },
    handleCheckBox(e, value, row) {
      const checked = e.target.checked;
      this.$set(this.checkedGroups, row.mforecastSalesId, checked);
      this.$emit('checked', this.checkedGroups, this.groups);
    },
    openDialog(dialog, rowInfo) {
      this[dialog] = true;
      this.currentRowInfo = rowInfo;
    },
    confirmDialog(e, modelCutRate) {
      if (this.currentRowInfo.dataIndex === 'modelNumber') {
        this.handleInputChange(
          Number(modelCutRate) || '',
          this.currentRowInfo.value,
          this.currentRowInfo.row,
          this.currentRowInfo.index,
          'modelCutRate'
        );
      }
      this.handleInputChange(
        e,
        this.currentRowInfo.value,
        this.currentRowInfo.row,
        this.currentRowInfo.index,
        this.currentRowInfo.dataIndex
      );
    },
    customRender(children, index, row, key) {
      const attrs = {};
      if (this.totalIndex.includes(index)) {
        if (key === 'changeRemark') {
          attrs.colSpan = 1;
        } else {
          attrs.colSpan = 0;
        }
      }
      if (!this.isEdit && (key === 'mforecastSalesId' || key === 'selection')) {
        const data = this.groups[row.mforecastSalesId];
        if (row.id === data[0].id) {
          attrs.rowSpan = data.length;
        } else {
          attrs.rowSpan = 0;
        }
      }
      return {
        children,
        attrs,
      };
    },
    handleSelectFileds(filedsKeys) {
      this.filedsKeys = filedsKeys;
    },

    totalAccount(type, record, index) {
      const value = _.get(record, type);
      const result = Object.keys(value || {}).reduce((pre, cur) => {
        if (cur !== 'total') {
          const n = Number(value[cur]) || 0;
          pre = pre.plus(new Decimal(n));
        }
        return pre;
      }, new Decimal(0));
      if (type === 'price') {
        return new Decimal(result).toFixed(2);
      }
      return new Decimal(result).toFixed();
    },

    createMonthColumns({
      key = 'fcst',
      hasTotal = true,
      months = this.monthObj,
      color = '#facd91',
    }) {
      const columns = Object.keys(months).map((month) => {
        const dataIndex = `${key}.${month}`;
        const monthItem = {
          align: 'center',
          title: month,
          width: 150,
          customHeaderCell: () => customHeaderCell(color),
          dataIndex,
          customRender: (text, row, index) => {
            const isSame =
              key !== 'fcst' ? true : row.changeRemark ? false : true;
            return <TableSpan value={text} isEdit={false} isSame={isSame} />;
          },
        };
        return monthItem;
      });
      if (hasTotal) {
        const totalDataIndex = `${key}.total`;
        columns.push({
          align: 'center',
          title: '汇总',
          width: 120,
          customHeaderCell: () => customHeaderCell(color),
          dataIndex: totalDataIndex,
          customRender: (text, row, index) => {
            return <TableSpan value={this.totalAccount(key, row)} />;
          },
        });
      }
      return columns;
    },
    handleInputChange(e, text, record, index, key) {
      const keys = ['mforecastSalesId', 'modelName'];
      if (keys.includes(key)) {
        this.$emit('update:has-compare', false);
      }
      if (key === 'mforecastSalesId') {
        record.mforecastSalesId = e;
      }
      if (key === 'm9RelationId') {
        record.price = JSON.parse(e.price || '{}');
        record.m9RelationId = e.relationId;
        return;
      }

      record[key] = e;
    },
    handleObjectInputChange(e, text, record, index, key) {
      _.set(record, key, e);
    },
    handleButtonClick(key) {
      const fn = `${key}Callback`;
      this[fn] && this[fn]();
    },

    async exportCallback() {
      const res = await postExportDetail({
        templateType: M_TEMPLATE['m9Total'],
        id: this.planId,
        mforecastSalesId: this.mforecastSalesId,
        idList: this.dataSourceFilter.map((item) => item.id),
      });
      await downloadFile(res.data, res.filename || '明细.xls');
    },
    showCallback() {
      this.visibleFiled = true;
    },
  },
};
</script>

<style lang="less" scoped>
.button-container {
  margin-bottom: 20px;
}
.poros-table td {
  white-space: nowrap;
}
.container {
  margin-bottom: 20px;
}
.table-list-container {
  margin-top: 10px;
}
.screenfull-container {
  background: #fff;
  padding: 20px;
}
</style>